package com.cooper.core;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.DefaultPropertiesPersister;
import org.springframework.util.PropertiesPersister;

import com.cooper.constants.ResourceConstants;
import com.cooper.util.HttpUtils;
import com.google.common.collect.Maps;

/**
 * 
* @Description: 
* @version: v1.0.0
* @author: tianlg
* @date: Mar 4, 2015 9:11:29 PM
*
* Modification History:
* Date         Author          Version            Description
*---------------------------------------------------------*
* Mar 4, 2015      tianlg          v1.0.0
 */
public class MinasPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
	
	private String getProperty(String key){
		Properties props = System.getProperties();
		String strValue = props.getProperty(key);
		if(StringUtils.isBlank(strValue)){
			strValue = System.getenv(key.toUpperCase());
		}
		if(StringUtils.isBlank(strValue)){
			strValue = Configuration.getInstance().getProperty(key);
		}
		return strValue;
	}
	
	@Override
	protected Properties mergeProperties() throws IOException {
		Properties oldProps = super.mergeProperties();
		String strResponse = this.downloadAndSaveMinasProps();
		
		PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
		ByteArrayInputStream bis = new ByteArrayInputStream(strResponse.toString().getBytes());
		propertiesPersister.load(oldProps, bis);
		return oldProps;
	}
	
	private String downloadAndSaveMinasProps() throws IOException{
		String minasUrl = this.getProperty("minas_url");
		String appKey = this.getProperty("minas_app_key");
		String appSecret = this.getProperty("minas_app_secret");
		String branchId = this.getProperty("minas_branch_id");
		
		if(StringUtils.isBlank(minasUrl)){
			logger.error("minas url is empty, please set it like as -Dminas_url=https://url_path ");
		} else if(StringUtils.isBlank(appKey)){
			logger.error("app_key is empty, please set it like as -Dminas_app_key=4516b72b651fe493 ");
		} else if(StringUtils.isBlank(appSecret)){
			logger.error("app_secret is empty, please set it like as -Dminas_app_secret=f91be09220d75994d1f241674ef21213 ");
		} else if(StringUtils.isBlank(branchId)){
			logger.error("branch_id is empty, please set it like as -Dminas_branch_id=20160926153212703a9f ");
		}
		
		String strResponse = null;
		try {
			strResponse = this.downloadMinasProperties(minasUrl, appKey, branchId, appSecret);
			if(strResponse.startsWith("{")){
				logger.error("download properties error, RESPONSE<<<===" + strResponse);
				return null;
			}
		} catch (Exception ex) {
			logger.error("download properties from minas error", ex);
		}
		
		return strResponse;
	}
	
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		try {
			Properties mergedProps = mergeProperties();
			
			// Convert the merged properties, if necessary.
			convertProperties(mergedProps);

			// Let the subclass process the properties.
			processProperties(beanFactory, mergedProps);
		} catch (IOException ex) {
			throw new BeanInitializationException("Could not load properties", ex);
		}
	}

	private String downloadMinasProperties(String minasUrl, String appKey, String branchId, String appSecret) throws Exception {
		Map<String, String> paramMap = Maps.newLinkedHashMap();
		paramMap.put("appKey", appKey);
		paramMap.put("branchId", branchId);
		
		String ts = String.valueOf(System.currentTimeMillis()/1000);
		paramMap.put("ts", ts);
		
		String sign = DigestUtils.md5Hex(appKey + branchId + ts + appSecret);
		paramMap.put("sign", sign);
		
		String strUrl = HttpUtils.assembleUrl(minasUrl, paramMap, ResourceConstants.CharSet.UTF8);
		logger.info("app_secret: " + appSecret + ", download minas properties from url: " + strUrl);
		return HttpUtils.httpsGet(strUrl, ResourceConstants.CharSet.UTF8, null);
	}
	
}
